package com.bub.pay.framework.common.template;

import org.springframework.beans.BeanUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 极光推送模板
 */
public class JPushTemplate {

    private static final Map<String, JPushVo> templateMap = new HashMap<>();
    private static ExpressionParser parser = new SpelExpressionParser();

    /*------------------------------------买家申诉----------------------------------------*/
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS = "1101";                //卖家提供错误付款信息,申诉成功,申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS_OPPOSITE = "1102";       //卖家提供错误付款信息,申诉成功,被申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_FAIL = "1103";                   //卖家提供错误付款信息,申诉失败,申诉者信息

    public final static String TEMPLATE_BUYER_APPEAL_SELLER_UNDO_SUCCESS = "1104";                      //付款后卖方不放行BUB,申诉成功,申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_UNDO_SUCCESS_OPPOSITE = "1105";             //付款后卖方不放行BUB,申诉成功,被申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_UNDO_FAIL = "1106";                         //付款后卖方不放行BUB,申诉失败,申诉者信息

    public final static String TEMPLATE_BUYER_APPEAL_BUYER_OUT_OF_TIME_SUCCESS = "1107";               //已付款，但未在时间内点击确认付款,申诉成功,申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_BUYER_OUT_OF_TIME_SUCCESS_OPPOSITE = "1108";      //已付款，但未在时间内点击确认付款,申诉成功,被申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_BUYER_OUT_OF_TIME_FAIL = "1109";                  //已付款，但未在时间内点击确认付款,申诉失败,申诉者信息

    public final static String TEMPLATE_BUYER_APPEAL_SELLER_OTHER = "1110";                             //其他原因,申诉者信息
    public final static String TEMPLATE_BUYER_APPEAL_SELLER_OTHER_OPPOSITE = "1111";                    //其他原因,被申诉者信息

    /*------------------------------------卖家申诉----------------------------------------*/
    public final static String TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS = "1201";   //已付款，买方未付款却标记已付款,申诉成功,申诉者信息
    public final static String TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS_OPPOSITE = "1202";   //已付款，买方未付款却标记已付款,申诉成功,被申诉者信息
    public final static String TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_FAIL = "1203";   //已付款，买方未付款却标记已付款,申诉失败,申诉者信息

    public final static String TEMPLATE_SELLER_APPEAL_BUYER_OTHER_REASON = "1204";   //其他原因,申诉者信息
    public final static String TEMPLATE_SELLER_APPEAL_BUYER_OTHER_REASON_OPPOSITE = "1205";   //其他原因,被申诉者信息

    /*------------------------标题---------------------------*/
    public final static String APPEAL_SUCCESS_TITLE = "申诉成功";
    public final static String APPEAL_SUCCESS_TITLE_OPPOSITE = "被申诉成功";
    public final static String APPEAL_FAIL_TITLE = "申诉失败";

    /*---------------------------------内容----------------------------------*/
    public final static String CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS = "经过币友团队审核，发现该商户收款信息填写错误，已为您取消此次交易，并预祝您在BUB的交易顺心。<br>交易订单号{orderNO}";
    public final static String CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS_OPPOSITE = "经过币友团队审核，买家申诉您的收款方式有有误属实，请前往修正。<br>交易订单号{orderNO}<br>系统已将您信息有误的收款方式关闭，" +
            "如您收款方式唯一且有误，系统会将您的广告下架，请您修正完成后再重新上架，币友团队在此感谢您的配合，并祝您在币友交易顺心。";
    public final static String CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_FAIL = " 经过币友团队审核，发现该商户收款信息填写正确，请重新尝试交易。<br>交易订单号{orderNO}";

    public final static String CONTENT_BUYER_APPEAL_SELLER_UNDO_SUCCESS = "经过币友团队审核，已向商家确认此次订单有效，此次交易应得BUB已转至您的BUB钱包，并预祝您在币友的交易顺心。<br>交易订单号{orderNO}";
    public final static String CONTENT_BUYER_APPEAL_SELLER_UNDO_SUCCESS_OPPOSITE = "经过币友团队审核，买家申诉已付款超过1小时但您未放行BUB属实，系统已执行放行操作。<br>交易订单号{orderNO}";
    public final static String CONTENT_BUYER_APPEAL_SELLER_UNDO_FAIL = "经币友团队审核，由于您未能提拱有效已付款证明，因此本次申诉失败，有问题请联系客服人员。<br>交易订单号{orderNO}";

    public final static String CONTENT_BUYER_APPEAL_BUYER_OUT_OF_TIME_SUCCESS = "经过币友团队审核，已向商家确认此次订单有效，此次交易应得BUB已转至您的BUB钱包，并预祝您在币友的交易顺心。<br>交易订单号{orderNO}";
    public final static String CONTENT_BUYER_APPEAL_BUYER_OUT_OF_TIME_FAIL = "卖家未完成放行操作，根据币友交易规范，因买方操作因素导致交易失败，损失由买方承担，有问题请联系客服。<br>交易订单号{orderNO}";

    public final static String CONTENT_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS = "经过币友团队审核，此次交易是由买方因素造成，币友团队已帮您取消此次订单，预祝您在币友的交易顺心。<br>交易订单号{orderNO}";
    public final static String CONTENT_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS_OPPOSITE = "卖方申诉未收到您的汇款，经币友团队审核属实，系统已取消此次订单，并记录您无效订单1次。<br>交易订单号{orderNO}";
    public final static String CONTENT_SELLER_APPEAL_BUYER_UNPAYED_FAIL = "经过币友团队审核，您未能提供有效未收款证明，因此此次申诉失败，有问题请联系客服。<br>交易订单号{orderNO}";

    static {
        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS , new JPushVo(APPEAL_SUCCESS_TITLE,CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS));
        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS_OPPOSITE , new JPushVo(APPEAL_SUCCESS_TITLE_OPPOSITE,CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_SUCCESS_OPPOSITE));
        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_WRONG_INFO_FAIL , new JPushVo(APPEAL_FAIL_TITLE,CONTENT_BUYER_APPEAL_SELLER_WRONG_INFO_FAIL));

        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_UNDO_SUCCESS , new JPushVo(APPEAL_SUCCESS_TITLE,CONTENT_BUYER_APPEAL_SELLER_UNDO_SUCCESS));
        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_UNDO_SUCCESS_OPPOSITE , new JPushVo(APPEAL_SUCCESS_TITLE_OPPOSITE,CONTENT_BUYER_APPEAL_SELLER_UNDO_SUCCESS_OPPOSITE));
        templateMap.put(TEMPLATE_BUYER_APPEAL_SELLER_UNDO_FAIL , new JPushVo(APPEAL_FAIL_TITLE,CONTENT_BUYER_APPEAL_SELLER_UNDO_FAIL));

        templateMap.put(TEMPLATE_BUYER_APPEAL_BUYER_OUT_OF_TIME_SUCCESS , new JPushVo(APPEAL_SUCCESS_TITLE,CONTENT_BUYER_APPEAL_BUYER_OUT_OF_TIME_SUCCESS));
        templateMap.put(TEMPLATE_BUYER_APPEAL_BUYER_OUT_OF_TIME_FAIL , new JPushVo(APPEAL_FAIL_TITLE,CONTENT_BUYER_APPEAL_BUYER_OUT_OF_TIME_FAIL));

        templateMap.put(TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS , new JPushVo(APPEAL_SUCCESS_TITLE,CONTENT_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS));
        templateMap.put(TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS_OPPOSITE , new JPushVo(APPEAL_SUCCESS_TITLE_OPPOSITE,CONTENT_SELLER_APPEAL_BUYER_UNPAYED_SUCCESS_OPPOSITE));
        templateMap.put(TEMPLATE_SELLER_APPEAL_BUYER_UNPAYED_FAIL , new JPushVo(APPEAL_FAIL_TITLE,CONTENT_SELLER_APPEAL_BUYER_UNPAYED_FAIL));
    }


    public static JPushVo getContent(String templateId,Map<String,String> data,String registrationId, boolean isProd){
        JPushVo sourceModel = templateMap.get(templateId);
        if (sourceModel == null){
            return null;
        }
        handlerTemplateDataVariable(data);
        String title = sourceModel.getTitle();
        String content = sourceModel.getContent();

        JPushVo destinationModel = new JPushVo();
        Map<String,String> messageData = new HashMap<>();

        BeanUtils.copyProperties(sourceModel, destinationModel);

        destinationModel.setRegistrationId(registrationId);
        destinationModel.setProd(isProd);
        destinationModel.setTitle(processTemplate(title,data));
        destinationModel.setContent(processTemplate(content,data));

        return destinationModel;
    }

    /**
     * 处理模板
     *
     * @param template     模板
     * @param dataVariable 数据变量
     * @return 处理完毕后的模板
     */
    @SuppressWarnings("Duplicates")
    private synchronized static String processTemplate(String template, Map<String, String> dataVariable) {
        // 以模板方式解析
        EvaluationContext context = new StandardEvaluationContext();
        for (String key : dataVariable.keySet()) {
            String value = dataVariable.get(key);
            context.setVariable(key, value);
        }
        Expression expression = parser.parseExpression(template, TEMPLATE_EXPRESSION);
        template = expression.getValue(context, String.class);
        if(template == null){
            template = "";
        }
        // 转换{}变量
        for (String key : dataVariable.keySet()) {
            String value = dataVariable.get(key);
            if (template.contains(key)) {
                template = template.replaceAll("\\{" + key + "\\}", value);
            }
        }
        return template;
    }

    /**
     * 处理模板数据
     *
     * @param dataVariable 数据变量
     */
    private static void handlerTemplateDataVariable(Map<String, String> dataVariable) {
        Set<Map.Entry<String, JPushVo>> entrySet = templateMap.entrySet();
        for (Map.Entry<String, JPushVo> entry : entrySet) {
            String templateId = entry.getKey();
            JPushVo jPushVo = entry.getValue();
            dataVariable.put(String.format("template_%s_title", templateId), jPushVo.getTitle());
            dataVariable.put(String.format("template_%s_content", templateId), jPushVo.getContent());
        }
    }


    /**
     * 表达式模板解析器
     * 当使用此解析器时
     * 只有$()内的内容才会被识别为表达式进行解析
     */
    private static final ParserContext TEMPLATE_EXPRESSION = new ParserContext() {

        @Override
        public boolean isTemplate() {
            return true;
        }

        @Override
        public String getExpressionPrefix() {
            return "$(";
        }

        @Override
        public String getExpressionSuffix() {
            return ")";
        }
    };
}
